/**********************************************************************************************/
// dgt_Log.cpp
//
// Log mechanism for DStudio
// Copyright Diamant Group 2008
/**********************************************************************************************/
#include <iostream>
#include <map>
#include "dgtKernel.h"
#include "dgt_Log.h"
#include "dgt_BoolFunction.h"
#include "dgt_BoolElement.h"

using namespace std;

/************************************************************************************************/
ofstream		*gLogFile;
bool			isInit = false;

/************************************************************************************************/
void			OutBoolArray( BoolElementArray inValue );
void			OutWxStringArray( wxArrayString inValue );
void			OutBoolElement( dgt_BoolElement_Ptr inValue );

/************************************************************************************************/
void InitLog( void )
{
	time_t t;
	time(&t);
	struct tm* cur_time = localtime(&t);

	long year				= long( cur_time->tm_year + 1900 );
	unsigned short month 	= unsigned short( cur_time->tm_mon + 1);
	unsigned short day   	= (unsigned short) cur_time->tm_mday;

	unsigned short hours	= (unsigned short) cur_time->tm_hour;
	unsigned short minutes	= (unsigned short) cur_time->tm_min;
	unsigned short seconds	= (unsigned short) cur_time->tm_sec;

	// DGT_Log_YYYYMMDD_HHMMSS.log
	char filename[30];
	sprintf( filename, "DGT_Log_%.4ld%.2u%.2u%c%.2u%.2u%.2u.log", 
			year, month, day, '_', hours, minutes, seconds );
	
	gLogFile = new ofstream( filename );
	gLogFile->flush();

	isInit = true;
}

/************************************************************************************************/
void log_start( const char* inModuleName, const char* inFuncName )
{
#ifdef	dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << "-----\nMODULE " << inModuleName << ", FUNCTION " << inFuncName <<"\n";  
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								int inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								unsigned inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								long inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								unsigned long inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								double inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								wxString inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << " = " <<  inValue.c_str() << '\n'; 
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								wxArrayString inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(wxArrayString) =\n"; 
	OutWxStringArray( inValue );
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								wxArrayInt inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(wxArrayInt) =\n"; 
	for( unsigned i = 0; i < inValue.Count(); i++ )
		*gLogFile << "[" << inValue.Item( i ) << "]\n";
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								map<int, bool> inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(map<int, bool>) =\n"; 
	for( map<int, bool>::const_iterator p = inValue.begin(); p != inValue.end(); p++ )
		*gLogFile << p->first << ", " << p->second << "\n";
	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								BoolElementArray inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(BoolElementArray) =\n"; 
		
	OutBoolArray( inValue );

	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								dgt_BoolFunction_Ptr inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(dgt_BoolFunction_Ptr) =\n"; 
	
	NORMAL_KIND nKind = inValue->get_Kind();
	if( nKind == AND_OR )
		*gLogFile << "Form AND/OR\n";
	else if( nKind == NOTAND_NOTAND )
		*gLogFile << "Form NOTAND/NOTAND\n";
	else if( nKind == OR_NOTAND )
		*gLogFile << "Form OR/NOTAND\n";
	else if( nKind == NOTOR_OR )
		*gLogFile << "Form NOTOR/OR\n";
	else if( nKind == AND_NOTOR )
		*gLogFile << "Form AND/NOTOR\n";
	else if( nKind == NOTAND_AND )
		*gLogFile << "Form NOTAND/AND\n";
	else if( nKind == OR_AND )
		*gLogFile << "Form OR/AND\n";
	else if( nKind == NOTOR_NOTOR )
		*gLogFile << "Form NOTOR/NOTOR\n";

	*gLogFile << "VarNames = \n";
	OutWxStringArray( inValue->get_VarNames() );

	*gLogFile << "Elements = \n";
	BoolElementArray bArray = inValue->get_Function();
	OutBoolArray( bArray );

	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
								const char* inParamName, 
								dgt_LogicTable_Ptr inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << '\t' << inPrefix << inParamName << "(dgt_LogicTable_Ptr) =\n"; 
	
	*gLogFile << "VarNames = \n";
	
	wxArrayString tArray = inValue->get_VarNames();
	OutWxStringArray( tArray );

	*gLogFile << '\t' << inPrefix << inParamName << "Logic =\n"; 
	map<unsigned, bool> tVal = inValue->get_Values();
	for( map<unsigned, bool>::const_iterator p = tVal.begin(); p != tVal.end(); p++ )
		*gLogFile << p->first << ", " << p->second << "\n";

	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
							  const char* inParamName, 
							  dgt_AlgActArray inValue )
{

}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
							  const char* inParamName, 
							  dgt_AlgCondArray inValue )
{

}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
							  const char* inParamName, 
							  dgt_AlgLogArray inValue )
{

}

/************************************************************************************************/
void				log_param(	const char* inPrefix, 
							  const char* inParamName, 
							  dgt_AlgVarArray inValue )
{

}

/************************************************************************************************/
void				log_return( const char* inFuncName )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, int inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << (long) inValue << "\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, unsigned inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << (long) inValue << "\n";
	gLogFile->flush();
#endif
}


/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, long inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << inValue << "\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, unsigned long inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << inValue << "\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, double inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << inValue << "\n";
	gLogFile->flush();
#endif
}


/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, BoolElementArray inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(BoolElementArray)  = \n";
	OutBoolArray( inValue );
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, wxArrayString inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(wxArrayString)  = \n";
	OutWxStringArray( inValue );
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, wxArrayInt inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(wxArrayInt)  = \n";
	for( unsigned i = 0; i < inValue.Count(); i++ )
		*gLogFile << "[ " << i << " ] =  " << inValue.Item( i );
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, wxBoolArray inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(wxBoolArray)  = \n";
	for( unsigned i = 0; i < inValue.Count(); i++ )
		*gLogFile << "[ " << i << " ] =  " << inValue.Item( i );
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, wxString inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << " = " << inValue.c_str() << "\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, map<int, bool> inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(map<int, bool>)  = \n";
	for( map<int, bool>::const_iterator p = inValue.begin(); p != inValue.end(); p++ )
		*gLogFile << p->first << ", " << p->second << "\n";
	gLogFile->flush();
#endif
}

/**********************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, dgt_BoolFunction_Ptr inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();
	*gLogFile << inFuncName << " RETURN " << inName << "(dgt_BoolFunction_Ptr)  = \n";

	NORMAL_KIND nKind = inValue->get_Kind();
	if( nKind == AND_OR )
		*gLogFile << "Form AND/OR\n";
	else if( nKind == NOTAND_NOTAND )
		*gLogFile << "Form NOTAND/NOTAND\n";
	else if( nKind == OR_NOTAND )
		*gLogFile << "Form OR/NOTAND\n";
	else if( nKind == NOTOR_OR )
		*gLogFile << "Form NOTOR/OR\n";
	else if( nKind == AND_NOTOR )
		*gLogFile << "Form AND/NOTOR\n";
	else if( nKind == NOTAND_AND )
		*gLogFile << "Form NOTAND/AND\n";
	else if( nKind == OR_AND )
		*gLogFile << "Form OR/AND\n";
	else if( nKind == NOTOR_NOTOR )
		*gLogFile << "Form NOTOR/NOTOR\n";

	*gLogFile << "VarNames = \n";
	OutWxStringArray( inValue->get_VarNames() );

	*gLogFile << "Elements = \n";
	BoolElementArray bArray = inValue->get_Function();
	OutBoolArray( bArray );

	gLogFile->flush();
#endif
}

/************************************************************************************************/
void				log_return( const char* inFuncName, const char* inName, dgt_BoolElement_Ptr inValue )
{
#ifdef dgt_DEBUG
	if( !isInit )
		InitLog();

	OutBoolElement( inValue );
		
	gLogFile->flush();
#endif
}

void				log_return( const char* inFuncName, const char* inName, dgt_AlgActArray inValue ) {}	// TODO 
void				log_return( const char* inFuncName, const char* inName, dgt_AlgCondArray inValue ) {}	// TODO 
void				log_return( const char* inFuncName, const char* inName, dgt_AlgLogArray inValue ) {}	// TODO 
void				log_return( const char* inFuncName, const char* inName, dgt_AlgVarArray inValue ) {}	// TODO 

/************************************************************************************************/
void					OutBoolArray( BoolElementArray inValue )
{
	for( unsigned i = 0; i < inValue.Count(); i++ )
	{
		dgt_BoolElement_Ptr tElement = inValue.Item( i );
		OutBoolElement( tElement );
	}
}

/************************************************************************************************/
void					OutBoolElement( dgt_BoolElement_Ptr inValue )
{
	BOOL_OPERATION tOp = inValue->get_Operation();

	if( tOp == AND )
		*gLogFile << "AND (";
	else if( tOp == OR )
		*gLogFile << "OR (";
	else if( tOp == NOTAND )
		*gLogFile << "NOTAND (";
	else if( tOp == NOTOR )
		*gLogFile << "NOTOR (";

	wxArrayInt op = inValue->get_OpCodes();
	wxBoolArray inv = inValue->get_Inverts();

	unsigned long count = inValue->Count();

	for( unsigned j = 0; j < count; j++ )
	{
		int t_op = op.Item( j );

		*gLogFile << " " << t_op;
	}
	*gLogFile << " ) (";
	for( unsigned j = 0; j < count; j++ )
	{
		bool t_inv = inv.Item( j );

		*gLogFile << " " << t_inv;
	}
	*gLogFile << ")\n";	
}

/************************************************************************************************/
void					OutWxStringArray( wxArrayString inValue )
{
	*gLogFile << "\n";

	for( unsigned i = 0; i < inValue.Count(); i++ )
	{
		const wxChar* tStr = inValue.Item( i ).c_str();
		const char* tSttr = (const char*) tStr;
		*gLogFile << "[" << i << "] = " << tSttr << "\n";
		gLogFile->flush();
	}
}